# -*- coding: utf-8 -*-


# cmap2owl -- Helper application to convert from concept maps to OWL ontologies
# Copyright (c) 2008-2013  Rodrigo Rizzi Starr
#  
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#  
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#  
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.


'''
Contains general inferences dealing with relations

@author: Rodrigo Rizzi Starr
@copyright: Copyright © 2008-2013 Rodrigo Rizzi Starr
@license: MIT License
@contact: rodrigo.starr@gmail.com
'''


from infoProvider import SimpleInfoProvider
from mapperRule import MapperRule
from mapperQuestion import MapperQuestion
from CMap2Prolog import assemblyQuery
from log import log
log.debug('Loaded...')


class RelationRule(MapperRule):
    '''Simple rule to identify a relation'''
    
    def __init__(self, db):
          
        # Heuristics to identify relations
        rules = [
                 'inferenceGroup(relationRule, [relation(_)])',
                 'relation(Relation) :- linkingPhrase(Relation)',
                 'relationOWL(Relation) :- isTrue(relation(Relation))',
                 ]
          
        MapperRule.__init__(self, 'Relations', db, rules)

    def getQuestions(self):
        '''Returns a list of questions'''
        questions = []
        query = 'possible(relation(Relation)), ' \
                'fromSetRelation(Relation, FSet), ' \
                'toSetRelation(Relation, TSet)'
                
        relations = self.db.query(query)
        
        for answer in relations:
            answer['Ids'] = [answer['Relation']]
            answer['Ids'].extend(answer['FSet'])
            answer['Ids'].extend(answer['TSet'])
            
            questions.append(RelationQuestion(
                self.db,
                answer,
                'Is "<b>%(Relation)s</b>" an important relation?',
                'relation(%(Relation)s)',
                 helpFile = 'relation',
              ))
              
        return questions

    def getInfoProvider(self):
        '''Returns an info provider for individuals'''
        
        return SimpleInfoProvider(self.db,
                                     'isTrue(relation(%s))',
                                     'This element is an OWL relation')

    
class RelationQuestion(MapperQuestion):
    '''Updates the relation ids correctly in case of unification
    '''
    
    def updateIds(self):
        '''Return a set of updated ids'''

        queryTemplate = ('Relation = %(Relation)s, '
                         'possible(relation(Relation)), '
                         'fromSetRelation(Relation, FSet), '
                         'toSetRelation(Relation, TSet)'
                        )

        query = assemblyQuery(queryTemplate, self.data)
        answer = list(self.db.query(query))

        if len(answer) == 0:
            self.ids =  set([])
        elif len(answer) > 1:
            log.error('The answer for ' + self.queryIds + 
                      ' was %d results long. This is weird.' % len(answer))
        else:
            answer = answer[0]
            

            self.data['Ids']  = [answer['Relation']]
            self.data['Ids'].extend(answer['FSet'])
            self.data['Ids'].extend(answer['TSet'])
            
            self.ids = set(self.data['Ids'])
            
    def updateSensitivity(self):
        'Recalculates the status when the question changes'
        
        if not self.buttonPressed:
            self.updateIds()
            if len(self.ids) == 0:
                self.setAsInsensitive()
            else:
                self.setAsSensitive()
        else:
            self.setAsInsensitive()
    
